/**
 * Copyright 2009 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.code.sapien.security;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import com.google.code.sapien.service.SecurityService;
import com.google.inject.Inject;

/**
 * Intercepts methods that have been marked with the RequiresRole annotation and validates the permissions.
 * @author Adam
 * @version $Id$
 * 
 * Created on May 16, 2009 at 9:11:52 PM 
 */
public class SecurityInterceptor implements MethodInterceptor {

	/**
	 * The security service.
	 */
	private SecurityService securityService;

	/**
	 * {@inheritDoc}
	 * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
	 */
	public Object invoke(final MethodInvocation invocation) throws Throwable {
		final RequiresAdministrator requiresAdmin = resolveAnnotation(invocation);
		if (requiresAdmin != null && !securityService.isAdministrator()) {
			throw new SecurityException("Access denied for method " + invocation.getMethod().getName());
		}
		return invocation.proceed();
	}

	/**
	 * Returns the requires permission annotation if it exists and null if it does not.
	 * @param invocation The methodInvocation.
	 * @return The requires permission annotation if it exists and null if it does not.
	 */
	private RequiresAdministrator resolveAnnotation(final MethodInvocation invocation) {
		RequiresAdministrator annotation = null;
		final Method method = invocation.getMethod();
		if (method.isAnnotationPresent(RequiresAdministrator.class)) {
			annotation = method.getAnnotation(RequiresAdministrator.class);
		}
		return annotation;
	}

	/**
	 * Sets securityService.
	 * @param securityService the securityService to set.
	 */
	@Inject
	public void setSecurityService(final SecurityService securityService) {
		this.securityService = securityService;
	}
}
